package com.lh.controller;

import com.lh.entity.User;
import com.lh.service.CartService;
import com.lh.service.UserService;
import com.mysql.jdbc.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 普通用户和管理员共用一张表，通过角色权限控制
 * 为了方便代码的阅读性，将管理员和用户的控制层分开
 * 管理员：AdminController
 * 用户：UserController
 *
 * @Author: LuoHang
 * @Date: 2021/1/26 15:41
 * @Description
 */
@Controller
public class UserController {
    @Autowired
    private UserService userService;

    @Autowired
    private CartService cartService;


    @RequestMapping("/getCode")
    @ResponseBody
    public void getValidateCode(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        //生产验证码 清空响应对象在浏览器的缓存
        // 添加响应头 无缓存
        resp.setHeader("Pragma","No-cache");
        resp.setHeader("Cache-Control","No-cache");
        resp.setHeader("Expires","0");
        //   设置响应内容给是  mine格式
        resp.setContentType("image/jpeg");
        //创建一个图片对象 ，在图片对象上画图文本
        BufferedImage bi = new BufferedImage(140,40,BufferedImage.TYPE_3BYTE_BGR);
        // 创建要给画笔对象
        Graphics g = bi.getGraphics();
        //设置笔刷白色
        g.setColor(Color.WHITE);
        g.fillRect(0,0,140,40);



        // 设置干扰线条
        for(int i=0;i<30;i++) {
            g.setColor( new Color((int)(Math.random()*255),
                    (int)(Math.random()*255),
                    (int)(Math.random()*255))
            );
            g.drawLine((int)(Math.random()*100),
                    (int)(Math.random()*40),
                    (int)(Math.random()*100),
                    (int)(Math.random()*40));

        }

        // 设置画笔颜色
        g.setColor(Color.MAGENTA);
        //设置字体大小
        g.setFont(new Font("楷体",Font.ITALIC,30));
        // 在图片上写内容
        String code = getCodes();
        // 由于需要验证   先将验证码保存到session中
        req.getSession().setAttribute("validateCode",code);

        g.drawString(code,5,30);

        //响应给客户端
        ImageIO.write(bi,"jpeg",resp.getOutputStream());

    }

    private String getCodes(){
        String s = "";
        for(int i = 0 ;i < 4;i++){
            s+= getCode()+" ";
        }
        return s;
    }

    /**
     * 随机生产验证码
     * @return 随机验证码
     */
    private char getCode(){
        // 生产一个数字  48 +10
        int r = (int)(Math.random()*3);
        int c=0;
        if(r==0){
            //生产数字
            c =(int)(Math.random()*10+48);
        }else if(r==1){
            c =(int)(Math.random()*26+97);
        }else{
            c =(int)(Math.random()*26+65);
        }
        return  (char)c;
    }

    /**
     * 登录页面
     * 普通用户和管理员共用一张表，通过权限控制
     * 所以这里的登录和登录验证是和管理员用户共用的
     *
     * @return 视图模型
     */
    @RequestMapping("/login")
    public ModelAndView login() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("login");
        return modelAndView;
    }

    /**
     * 验证登录+Ajax
     *
     * @param username 前端发送过来的用户名
     * @param password 前端发送过来的密码
     * @param request  请求对象
     * @return 用户对象（JSON）
     */
    @RequestMapping("/checkLogin")
    @ResponseBody
    public User checkLogin(@RequestParam String username, @RequestParam String password, @RequestParam String validateCode, HttpServletRequest request) {
        String code = (String) request.getSession().getAttribute("validateCode");
        code = code.replace(" ","");
        if (!validateCode.equals(code)){
            return null;
        }
        Map<String, Object> map = new HashMap<>(2);
        map.put("username", username);
        map.put("password", password);
        User user = userService.login(map);
        if (user != null) {
            if (user.getStatus() == 1 || user.getStatus() == 3) {
                //更新用户的登录时间、登录IP、修改时间等信息
                Timestamp lastTime = user.getLoginTime();
                Timestamp loginTime = new Timestamp(System.currentTimeMillis());
                Map<String, Object> updateInfo = new HashMap<>(5);
                updateInfo.put("lastTime", lastTime);
                updateInfo.put("loginTime", loginTime);
                updateInfo.put("gmtModified", loginTime);
                updateInfo.put("loginIp", getIpAddress(request));
                updateInfo.put("id", user.getId());
                userService.update(updateInfo);

                //将当前登录用户的对象（用户所有信息存在session中）
                request.getSession().setAttribute("user", user);
            }

            if ("普通用户".equals(user.getRole().getRoleName())){
                Map<String,Integer> data = new HashMap<>(2);
                data.put("id",user.getId());
                data.put("status",1);
                user.setCartBuyNums(cartService.getCartNums(data));
            }
        }
        return user;
    }

    /**
     * 注册页面
     *
     * @return 视图模型
     */
    @RequestMapping("/register")
    public ModelAndView register() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("register");
        return modelAndView;
    }

    /**
     * 验证注册
     *
     * @param username 用户输入的用户名
     * @param password 用户输入的密码
     * @param email    用户输入的邮箱
     * @param request  请求对象
     * @return map是否注册成功
     */
    @RequestMapping("/checkRegister")
    @ResponseBody
    public Map<String, Object> checkRegister(@RequestParam String username, @RequestParam String password,
                                             @RequestParam String email, HttpServletRequest request) {
        Map<String, Object> map = new HashMap<>(6);
        map.put("username", username);
        map.put("password", password);
        map.put("email", email);
        //用户创建时间
        map.put("gmtCreate", new Timestamp(System.currentTimeMillis()));
        //用户注册的IP地址
        map.put("registerIp", getIpAddress(request));
        //默认情况下用户注册就是普通用户（1:管理员；2:普通用户）
        map.put("roleId", 2);
        int count = userService.register(map);
        Map<String, Object> res = new HashMap<>(1);
        if (count > 0) {
            res.put("data", "注册成功");
        } else {
            res.put("data", "注册失败");
        }
        return res;
    }

    /**
     * 后台用户管理之用户列表
     *
     * @return 视图模型
     */
    @RequestMapping("/userList")
    public ModelAndView userList() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("admin/user_list");
        return modelAndView;
    }

    /**
     * 后台用户管理之获取用户对象集合
     * 包含条件模糊分页查询，用户角色区分
     * 所有的查询条件和角色ID存在map集合中传给Dao层
     * 由于普通用户和管理员公用一张表，所以管理员的列表模糊查询等操作也是在这里完成的
     * <p>
     * roleId 角色id 用于区分用户角色 1：管理员  2：普通用户 3：商家
     *
     * @param limit 用于分页需要查询每一页的条数
     * @param page  当前是第几页
     * @return lay_ui数据表格需要的数据格式  springMVC中导入Jackson的jar包后会自动解析（key-value形式）对象成json格式
     * 但是必须带上@ResponseBody，其意义是将（json格式）数据写入到响应体中
     */
    @RequestMapping("/getUsers")
    @ResponseBody
    public Map<String, Object> getUsers(HttpServletRequest request, @RequestParam Integer limit,
                                        @RequestParam Integer page) {
        //后台分页模糊查询需要的数据
        Map<String, Object> query = new HashMap<>(15);

        //条件模糊查询
        String id = request.getParameter("id");
        String username = request.getParameter("username");
        String sex = request.getParameter("sex");
        String status = request.getParameter("status");
        String roleId = request.getParameter("roleId");
        if (!StringUtils.isNullOrEmpty(id)) {
            query.put("id", Integer.valueOf(id));
        }
        if (!StringUtils.isNullOrEmpty(username)) {
            query.put("userName", username);
        }
        String test = "请选择";
        if (!test.equals(sex)) {
            query.put("sex", sex);
        }
        if (!StringUtils.isNullOrEmpty(status) && !test.equals(status)) {
            query.put("status", Integer.parseInt(status));
        }

        //角色分类：1管理员，2普通用户，3商家
        if (!StringUtils.isNullOrEmpty(roleId) && !test.equals(roleId)) {
            query.put("roleId", Integer.valueOf(roleId));
        }

        //分页
        query.put("beginSize", limit * (page - 1));
        query.put("limit", limit);
        //获取的结果集合
        List<User> userList = userService.getUsers(query);

        //前端需要的数据
        Map<String, Object> map = new HashMap<>(4);
        map.put("code", 0);
        map.put("msg", "");
        map.put("count", userService.getCount(query));
        map.put("data", userList);
        return map;
    }

    /**
     * 后台用户管理之用户添加页面
     *
     * @return 视图模型
     */
    @RequestMapping("/addUserHtml")
    public ModelAndView addUserHtml() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("admin/user_add");
        return modelAndView;
    }

    @RequestMapping("/addUser")
    @ResponseBody
    public Map<String, Object> addUser(HttpServletRequest request, @RequestParam String username,
                                       @RequestParam Integer age, @RequestParam String phone, @RequestParam String email,
                                       @RequestParam String password, @RequestParam Integer roleId) {
        String sex = request.getParameter("sex");
        Map<String, Object> map = new HashMap<>(9);
        map.put("userName", username);
        map.put("sex", sex);
        map.put("age", age);
        map.put("phone", phone);
        map.put("email", email);
        map.put("passWord", password);
        map.put("gmtCreate", new Timestamp(System.currentTimeMillis()));
        map.put("registerIp", getIpAddress(request));
        map.put("roleId", roleId);
        int count = userService.addUser(map);
        Map<String, Object> res = new HashMap<>(1);
        res.put("data", count > 0 ? "添加成功" : "添加失败");
        return res;
    }

    /**
     * 后台用户管理之用户信息查看功能
     *
     * @param id 当前需要查看用户信息对应的ID
     * @return 视图模型
     */
    @RequestMapping("/userInfoView")
    public ModelAndView userInfoView(@RequestParam Integer id) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("userInfo", getUserById(id));
        modelAndView.setViewName("admin/user_view");
        return modelAndView;
    }

    /**
     * 后台用户管理之用户信息编辑页面
     *
     * @return 视图模型
     */
    @RequestMapping("/userEdit")
    public ModelAndView userEdit(@RequestParam Integer id) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("userInfo", getUserById(id));
        modelAndView.setViewName("admin/user_edit");
        return modelAndView;
    }

    /**
     * 后台用户管理之用户更新功能
     *
     * @param request 请求对象
     * @param id      需要更新的用户对应的ID
     * @return 是否更新成功
     */
    @RequestMapping("/updateUser")
    @ResponseBody
    public Map<String, Object> userUpdate(HttpServletRequest request, @RequestParam Integer id) {
        //用request来接收username...等是因为可能没有传送它们
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String sex = request.getParameter("sex");
        String age = request.getParameter("age");
        String phone = request.getParameter("phone");
        String email = request.getParameter("email");
        String status = request.getParameter("status");

        //获取需要更新数据的对应用户原始的信息对象，用于比对那些信息是需要更新的
        User user = getUserById(id);
        Map<String, Object> map = new HashMap<>(7);
        //将id和需要修改的信息存储到map集合中
        map.put("id", id);
        //修改时间
        map.put("gmtModified", new Timestamp(System.currentTimeMillis()));
        //!StringUtils.isNullOrEmpty(username)以及user的get()方法写在后面都是防止空指针异常
        if (!StringUtils.isNullOrEmpty(username) && !username.equals(user.getUserName())) {
            map.put("userName", username);
        }
        if (!StringUtils.isNullOrEmpty(password) && !password.equals(user.getPassWord())) {
            map.put("passWord", password);
        }
        if (!StringUtils.isNullOrEmpty(sex) && !sex.equals(user.getSex())) {
            map.put("sex", sex);
        }
        //Integer.parseInt()返回的是基本数据类型int Integer.valueOf()返回的才是Integer引用包装类型
        //年龄可能会超过127，Integer在-128-127之间是之间可以用==与int比较是否相等，超过范围则需要用equals
        if (!StringUtils.isNullOrEmpty(age) && !Integer.valueOf(age).equals(user.getAge())) {
            map.put("age", Integer.parseInt(age));
        }
        if (!StringUtils.isNullOrEmpty(phone) && !phone.equals(user.getPhone())) {
            map.put("phone", phone);
        }
        if (!StringUtils.isNullOrEmpty(email) && !email.equals(user.getEmail())) {
            map.put("email", email);
        }
        //status:0或1,在-128到127之间，直接用!=比较
        if (!StringUtils.isNullOrEmpty(status) && Integer.parseInt(status) != user.getStatus()) {
            map.put("status", Integer.parseInt(status));
        }
        Map<String, Object> res = new HashMap<>(1);
        res.put("data", updateUser(map) > 0 ? "更新成功" : "更新失败");
        return res;
    }

    /**
     * 后台用户管理之用户删除功能
     *
     * @param id 需要删除的用户对应的ID
     * @return 是否删除成功
     */
    @RequestMapping("/deleteUserById")
    @ResponseBody
    public Map<String, Object> deleteUserById(@RequestParam Integer id) {
        int count = userService.deleteUserById(id);
        Map<String, Object> map = new HashMap<>(1);
        map.put("data", count > 0 ? "删除成功" : "删除失败");
        return map;
    }


    /**
     * 通过ID查询对应的用户对象
     * 用于用户的基本信息查看功能，对普通用户和管理员用户都适用
     *
     * @param id 需要查询用户的对象
     * @return 当前ID所对应的用户对象
     */
    private User getUserById(Integer id) {
        return userService.getUserById(id);
    }

    /**
     * 更新
     *
     * @param map 需要更新的用户信息
     * @return 影响的行数count int
     */
    private int updateUser(Map<String, Object> map) {
        return userService.update(map);
    }

    /**
     * 获取客户端发送请求的ip地址
     *
     * @param request 请求对象
     * @return 请求IP地址
     */
    private String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        String test = "unknown";
        if (ip == null || ip.length() == 0 || test.equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || test.equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || test.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || test.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || test.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /*
     *商户列表操作
     */

    /**
     * 后台商户列表页面
     *
     * @return 视图模型
     */
    @RequestMapping("/merchantList")
    public ModelAndView merchantList() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("admin/merchant_list");
        return modelAndView;
    }

    /**
     * 后台用户管理之商户添加页面
     *
     * @return 视图模型
     */
    @RequestMapping("/addMerchantHtml")
    public ModelAndView addMerchantHtml() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("admin/merchant_add");
        return modelAndView;
    }

    /**
     * 后台用户管理之商户信息编辑页面
     *
     * @return 视图模型
     */
    @RequestMapping("/merchantEdit")
    public ModelAndView merchantEdit(@RequestParam Integer id) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("userInfo", getUserById(id));
        modelAndView.setViewName("admin/merchant_edit");
        return modelAndView;
    }

    /**
     * 后台用户管理之禁用用户账号列表页面
     *
     * @return 视图模型
     */
    @RequestMapping("/userLimitList")
    public ModelAndView userLimitList() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("admin/userLimit_list");
        return modelAndView;
    }

    /**
     * 禁用账号激活
     *
     * @param id 需要激活的账号对应的id
     * @return 是否激活成功
     */
    @RequestMapping("/userActive")
    @ResponseBody
    public Map<String, Object> userActive(@RequestParam Integer id) {
        //需要更新的数据
        Map<String, Object> map = new HashMap<>(3);
        map.put("id", id);
        map.put("gmtModified", new Timestamp(System.currentTimeMillis()));
        map.put("status", 1);

        int count = userService.update(map);
        Map<String, Object> res = new HashMap<>(1);
        res.put("data", count > 0 ? "启用成功" : "启用失败");
        return res;
    }
}
